#pragma once

#define COMM_VERSION					"3.0.2"
#define COMM_STRING_DEFAULT_LENGTH		2048
#define COMM_STACKTRACER_MAX_FRAMES		32


// define COMM_X64
//
#ifdef _MSC_VER
	#define COMM_MSVC
	#ifdef _WIN64
	#define COMM_X64
	#endif
#else
	#ifdef __x86_64__
	#define COMM_X64
	#endif
#endif


// supported feature.
//
#define COMM_FEATURE_LIBEVENT	1		// depend LIBEVENT
#define COMM_FEATURE_SSL		0		// depend OPENSSL
#define COMM_FEATURE_REGEX		1		// depend PCRE
#ifdef COMM_MSVC
#define COMM_FEATURE_STDLIST	0		// depend std::list
#else
#define COMM_FEATURE_STDLIST	1
#endif


// reference platform header files.
//
#ifndef COMM_MSVC
	#define _FILE_OFFSET_BITS 64	//fseeko and ftello support 64 bit.
#endif
#include <stdlib.h>
#include <stdio.h>
#include <assert.h>
#include <stdarg.h>
#include <time.h>
#include <string.h>
#include <sys/stat.h>
#include <list>
#include <vector>
#include <string>
#include <map>
#ifdef COMM_MSVC
	// Windows
	#define WIN32_LEAN_AND_MEAN 
	#include <WinSock2.h>
	#include <Windows.h>
	#include <io.h>
	#include <direct.h>
#elif defined(__GNUC__)
	// GNU Linux
	#include <unistd.h>
	#include <syslog.h>
	#include <signal.h>
	#include <errno.h>
	#include <unistd.h>
	#include <pwd.h>
	#include <ctype.h>
	#include <sys/time.h>
	#include <sys/types.h>
	#include <sys/wait.h>
	#include <fcntl.h>
	#include <pthread.h>
	#include <semaphore.h>
	#include <sys/socket.h>
	#include <sys/un.h>
	#include <netinet/in.h>
	#include <arpa/inet.h>
	// ASAN enable: 
	// link: libasan
	// CFLAGS: CFLAG=-fsanitize=address -fno-omit-frame-pointer
	// LD_PRELOAD=/usr/lib/x86_64-linux-gnu/libasan.so.2 ./test 
#else
	#error "*** UNSUPPORTED PLATFORM ! ***"
#endif


// define export macro COMM_API.
//
#if !defined(COMM_MSVC) || defined(_LIB) || defined(COMM_LIB)
	#define COMM_API 
#elif defined(LIBCOMM_EXPORTS)
	#define COMM_API __declspec(dllexport)
#else
	#define COMM_API __declspec(dllimport)
#endif


// global functions implement.
//
COMM_API const char* common_version();
COMM_API void common_dumpstack(int signo, FILE* stream=NULL);
COMM_API void common_log(int level, const char* format, ...);


// define hardware memory fence, 
// which prevents the processor from moving reads and writes across the fence.
//
#ifdef COMM_MSVC
#define MYLIB_MEMORY_FENCE	MemoryBarrier(); // MemoryBarrier has platform specific implementations for x86, x64 and IA64.
#else
#define MYLIB_MEMORY_FENCE	__sync_synchronize();
#endif


// define error message macro.
//
#ifdef COMM_MSVC
class COMM_API CommErrorString
{
public:
	explicit CommErrorString(DWORD errnum):m_lpMsgBuf(NULL){
		FormatMessageA( 
			FORMAT_MESSAGE_ALLOCATE_BUFFER | 
			FORMAT_MESSAGE_FROM_SYSTEM | 
			FORMAT_MESSAGE_IGNORE_INSERTS,
			NULL,
			errnum,
			MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
			(LPSTR) &m_lpMsgBuf,
			0,
			NULL 
			);
	}
	~CommErrorString(){ if(NULL!=m_lpMsgBuf){ LocalFree(m_lpMsgBuf);}}
	operator char*() const{ return (char*)m_lpMsgBuf;}
private:
	CommErrorString(const CommErrorString& inst){}
	CommErrorString& operator=(const CommErrorString& rhs){ return *this;}
	LPVOID m_lpMsgBuf;
};
#define MYLIB_ERRNO				(::GetLastError())
#define MYLIB_ERRNO_WSA			(::WSAGetLastError())
#define MYLIB_STRERROR(errnum)	((char*)CommErrorString(errnum))
#else
#define MYLIB_ERRNO				errno
#define MYLIB_STRERROR(errnum)	strerror(errnum)
#endif


// define log macro.
//
#define	MYLIB_LOG_ERR		3	
#define	MYLIB_LOG_WARNING	4	
#define	MYLIB_LOG_NOTICE	5	
#define	MYLIB_LOG_INFO		6	
#define	MYLIB_LOG_DEBUG		7
#define MYLIB_LOG(level,format,...)	common_log(level, format, ## __VA_ARGS__)
#define LOGERR(format,...)			MYLIB_LOG(MYLIB_LOG_ERR,format,## __VA_ARGS__)
#define LOGWARN(format,...)			MYLIB_LOG(MYLIB_LOG_WARNING,format,## __VA_ARGS__)
#define LOGNOTICE(format,...)		MYLIB_LOG(MYLIB_LOG_NOTICE,format,## __VA_ARGS__)
#define LOGINFO(format,...)			MYLIB_LOG(MYLIB_LOG_INFO,format,## __VA_ARGS__)
#define LOGDEBUG(format,...)		MYLIB_LOG(MYLIB_LOG_DEBUG,format,## __VA_ARGS__)
#define LOGFUNCERROR(func)			LOGERR("%s:%d: %s: Function \'%s\' error: (%d) %s", __FILE__,  __LINE__, __FUNCTION__, # func, MYLIB_ERRNO,MYLIB_STRERROR(MYLIB_ERRNO))
#define LOGFUNCERRORNO(func,error)	LOGERR("%s:%d: %s: Function \'%s\' error: (%d) %s", __FILE__,  __LINE__, __FUNCTION__, # func, error,MYLIB_STRERROR(error))
#ifdef COMM_MSVC
#define LOGFUNCERRORWSA(func)		LOGERR("%s:%d: %s: Function \'%s\' error: (%d) %s", __FILE__,  __LINE__, __FUNCTION__, # func, MYLIB_ERRNO_WSA,MYLIB_STRERROR(MYLIB_ERRNO_WSA))
#endif

// define assert macro
//
#define MYLIB_SIGUSR2	12
#define MYLIB_ASSERT(_Expression) {if(!(_Expression)){	\
	LOGERR("%s:%d: %s: Assertion \'%s\' failed.", __FILE__, __LINE__, __FUNCTION__, # _Expression);	\
	common_dumpstack(MYLIB_SIGUSR2);	\
	::exit(EXIT_FAILURE);	\
}}
#define MYLIB_ASSERT_ERRNO(_Expression) {if(!(_Expression)){	\
	LOGERR("%s:%d: %s: Assertion \'%s\' failed: (%d) %s", __FILE__, __LINE__, __FUNCTION__, # _Expression, MYLIB_ERRNO,MYLIB_STRERROR(MYLIB_ERRNO));	\
	common_dumpstack(MYLIB_SIGUSR2);	\
	::exit(EXIT_FAILURE);	\
}}
#define MYLIB_ASSERT_VALUE(_WishedVal,_Expression) {int _ReturnVal;if(_WishedVal != (_ReturnVal=(_Expression))){	\
	LOGERR("%s:%d: %s: Assertion \'%s\' failed: (%d) %s", __FILE__, __LINE__, __FUNCTION__, #_WishedVal"=="# _Expression, _ReturnVal,MYLIB_STRERROR(_ReturnVal));	\
	common_dumpstack(MYLIB_SIGUSR2);	\
	::exit(EXIT_FAILURE);	\
}}
#define MYLIB_ASSERT_SILENCE(_Expression) {if(!(_Expression)){	\
	fprintf(stderr,"%s:%d: %s: Assertion \'%s\' failed.\n", __FILE__, __LINE__, __FUNCTION__, # _Expression);	\
	common_dumpstack(MYLIB_SIGUSR2,stderr);	\
	::exit(EXIT_FAILURE);	\
}}
#define MYLIB_ASSERT_NOTNULL(_Var)	MYLIB_ASSERT(0!=(_Var))


// define non-copied class.
//
#define MYLIB_NONCOPIED_CLASS(cls)	\
private:	\
	cls(const cls& rhs){}	\
	cls& operator=(const cls& rhs){ return *this;}

// define max and min.
//
#define MYLIB_MAX(a,b)    (((a) > (b)) ? (a) : (b))
#define MYLIB_MIN(a,b)    (((a) < (b)) ? (a) : (b))

// define TLS 
#ifdef COMM_MSVC
#define MYLIB_TLS	__declspec(thread)
#else
#define MYLIB_TLS	__thread
#endif





